<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- 
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License. 
-->
<html>
<head>
    <link type="text/css" rel="stylesheet" href="https://struts.apache.org/css/default.css">
    <style type="text/css">
        .dp-highlighter {
            width:95% !important;
        }
    </style>
    <style type="text/css">
        .footer {
            background-image:      url('https://cwiki.apache.org/confluence/images/border/border_bottom.gif');
            background-repeat:     repeat-x;
            background-position:   left top;
            padding-top:           4px;
            color:                 #666;
        }
    </style>
    <link href='https://struts.apache.org/highlighter/style/shCoreStruts.css' rel='stylesheet' type='text/css' />
    <link href='https://struts.apache.org/highlighter/style/shThemeStruts.css' rel='stylesheet' type='text/css' />
    <script src='https://struts.apache.org/highlighter/js/shCore.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushPlain.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushXml.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushJava.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushJScript.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushGroovy.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushBash.js' type='text/javascript'></script>
    <script type="text/javascript">
        SyntaxHighlighter.defaults['toolbar'] = false;
        SyntaxHighlighter.all();
    </script>
    <script type="text/javascript" language="javascript">
        var hide = null;
        var show = null;
        var children = null;

        function init() {
            /* Search form initialization */
            var form = document.forms['search'];
            if (form != null) {
                form.elements['domains'].value = location.hostname;
                form.elements['sitesearch'].value = location.hostname;
            }

            /* Children initialization */
            hide = document.getElementById('hide');
            show = document.getElementById('show');
            children = document.all != null ?
                    document.all['children'] :
                    document.getElementById('children');
            if (children != null) {
                children.style.display = 'none';
                show.style.display = 'inline';
                hide.style.display = 'none';
            }
        }

        function showChildren() {
            children.style.display = 'block';
            show.style.display = 'none';
            hide.style.display = 'inline';
        }

        function hideChildren() {
            children.style.display = 'none';
            show.style.display = 'inline';
            hide.style.display = 'none';
        }
    </script>
    <title>Localization</title>
</head>
<body onload="init()">
<table border="0" cellpadding="2" cellspacing="0" width="100%">
    <tr class="topBar">
        <td align="left" valign="middle" class="topBarDiv" align="left" nowrap>
            &nbsp;<a href="home.html">Home</a>&nbsp;&gt;&nbsp;<a href="guides.html">Guides</a>&nbsp;&gt;&nbsp;<a href="core-developers-guide.html">Core Developers Guide</a>&nbsp;&gt;&nbsp;<a href="localization.html">Localization</a>
        </td>
        <td align="right" valign="middle" nowrap>
            <form name="search" action="https://www.google.com/search" method="get">
                <input type="hidden" name="ie" value="UTF-8" />
                <input type="hidden" name="oe" value="UTF-8" />
                <input type="hidden" name="domains" value="" />
                <input type="hidden" name="sitesearch" value="" />
                <input type="text" name="q" maxlength="255" value="" />
                <input type="submit" name="btnG" value="Google Search" />
            </form>
        </td>
    </tr>
</table>

<div id="PageContent">
    <div class="pageheader" style="padding: 6px 0px 0px 0px;">
        <!-- We'll enable this once we figure out how to access (and save) the logo resource -->
        <!--img src="/wiki/images/confluence_logo.gif" style="float: left; margin: 4px 4px 4px 10px;" border="0"-->
        <div style="margin: 0px 10px 0px 10px" class="smalltext">Apache Struts 2 Documentation</div>
        <div style="margin: 0px 10px 8px 10px"  class="pagetitle">Localization</div>

        <div class="greynavbar" align="right" style="padding: 2px 10px; margin: 0px;">
            <a href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=14043">
                <img src="https://cwiki.apache.org/confluence/images/icons/notep_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Edit Page"></a>
            <a href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=14043">Edit Page</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/listpages.action?key=WW">
                <img src="https://cwiki.apache.org/confluence/images/icons/browse_space.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Browse Space"></a>
            <a href="https://cwiki.apache.org/confluence/pages/listpages.action?key=WW">Browse Space</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=WW&fromPageId=14043">
                <img src="https://cwiki.apache.org/confluence/images/icons/add_page_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Add Page"></a>
            <a href="https://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=WW&fromPageId=14043">Add Page</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/createblogpost.action?spaceKey=WW&fromPageId=14043">
                <img src="https://cwiki.apache.org/confluence/images/icons/add_blogentry_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Add News"></a>
            <a href="https://cwiki.apache.org/confluence/pages/createblogpost.action?spaceKey=WW&fromPageId=14043">Add News</a>
        </div>
    </div>

    <div class="pagecontent">
        <div class="wiki-content">
            <div id="ConfluenceContent"><p><style type="text/css">/*<![CDATA[*/
div.rbtoc1441088113804 {padding: 0px;}
div.rbtoc1441088113804 ul {list-style: disc;margin-left: 0px;}
div.rbtoc1441088113804 li {margin-left: 0px;padding-left: 0px;}

/*]]>*/</style></p><div class="toc-macro rbtoc1441088113804">
<ul class="toc-indentation"><li><a shape="rect" href="#Localization-Overview">Overview</a></li><li><a shape="rect" href="#Localization-ResourceBundleSearchOrder">Resource Bundle Search Order</a>
<ul class="toc-indentation"><li><a shape="rect" href="#Localization-Defaultaction'sclass">Default action's class</a></li><li><a shape="rect" href="#Localization-UsinggetTextfromaTag">Using getText from a Tag</a></li><li><a shape="rect" href="#Localization-Usingthetexttag">Using the text tag</a></li><li><a shape="rect" href="#Localization-UsingtheI18ntag">Using the I18n tag</a></li><li><a shape="rect" href="#Localization-UsingtheKeyattributeofUITags">Using the Key attribute of UI Tags</a></li></ul>
</li><li><a shape="rect" href="#Localization-I18nInterceptor">I18n Interceptor</a></li><li><a shape="rect" href="#Localization-GlobalResources(struts.custom.i18n.resources)instruts.properties">Global Resources (struts.custom.i18n.resources) in struts.properties</a></li><li><a shape="rect" href="#Localization-FormattingDatesandNumbers">Formatting Dates and Numbers</a></li><li><a shape="rect" href="#Localization-ComparisonwithStruts1">Comparison with Struts 1</a></li><li><a shape="rect" href="#Localization-Next:">Next: Type Conversion</a></li></ul>
</div><h2 id="Localization-Overview">Overview</h2><p>The framework supports internationalization (i18n) in the following places:</p><ol><li>the <a shape="rect" href="ui-tags.html">UI Tags</a></li><li>Messages and Errors from the <a shape="rect" class="external-link" href="http://struts.apache.org/2.0.6/struts2-core/apidocs/index.html?com/opensymphony/xwork2/ValidationAware.html">ValidationAware</a> interface (implemented by <a shape="rect" class="external-link" href="http://struts.apache.org/2.0.6/struts2-core/apidocs/index.html?com/opensymphony/xwork2/ActionSupport.html">ActionSupport</a> and <a shape="rect" class="external-link" href="http://struts.apache.org/2.0.6/struts2-core/apidocs/index.html?com/opensymphony/xwork2/ValidationAwareSupport.html">ValidationAwareSupport</a>)</li><li>Within action classes that extend <a shape="rect" class="external-link" href="http://struts.apache.org/2.0.6/struts2-core/apidocs/index.html?com/opensymphony/xwork2/ActionSupport.html">ActionSupport</a> through the getText() method</li></ol><h2 id="Localization-ResourceBundleSearchOrder">Resource Bundle Search Order</h2><p></p><p></p><p>Resource bundles are searched in the following order:</p>

<p></p><ol><li>ActionClass.properties</li><li>Interface.properties (every interface and sub-interface)</li><li>BaseClass.properties (all the way to Object.properties)</li><li>ModelDriven's model (if implements ModelDriven), for the model object repeat from 1</li><li>package.properties (of the directory where class is located and every parent directory all the way to the root directory)</li><li>search up the i18n message key hierarchy itself</li><li>global resource properties</li></ol>
For more, see the LocalizedTextUtil class.<div class="confluence-information-macro confluence-information-macro-tip"><p class="title">Package hierarchy</p><span class="aui-icon aui-icon-small aui-iconfont-approve confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p></p><p></p><p>To clarify #5, while traversing the package hierarchy, Struts 2 will look for a file package.properties:</p>
com/<br clear="none">
&#160; acme/<br clear="none">
&#160; &#160; package.properties<br clear="none">
&#160; &#160; actions/<br clear="none">
&#160; &#160; &#160; package.properties<br clear="none">
&#160; &#160; &#160; FooAction.java<br clear="none">
&#160; &#160; &#160; FooAction.properties<br clear="none">
<p>
If FooAction.properties does not exist, com/acme/action/package.properties will be searched for, if
not found com/acme/package.properties, if not found com/package.properties, etc.
</p></div></div><h3 id="Localization-Defaultaction'sclass">Default action's class</h3><p>If you configure action as follow</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;action name="index"&gt;
   &lt;result&gt;/index.jsp&lt;/result&gt;
&lt;/action&gt;</pre>
</div></div><p>it will use a default class defined with&#160;<code>default-class-ref</code><span style="color: rgb(34,34,34);">&#160;in&#160;<code>struts-default.xml</code> which is&#160;<code>com.opensymphony.xwork2.ActionSupport</code>. It means you have two options here to get I18N working in that case:</span></p><ul><li><span style="color: rgb(34,34,34);">define&#160;<code>com/opensymphony/xwork2/ActionSupport.properties</code> and put messages there</span></li><li><span style="color: rgb(34,34,34);">point&#160;<code>default-class-ref</code> to your base class and then defined appropriated <code>.properties</code>&#160;file (corresponding to class' name or package)</span></li></ul><p><span style="font-size: 20.0px;line-height: 1.5;">Examples</span></p><p>There are several ways to access the message resources, including <code>getText</code>, the <code>text</code> tag, and the <code>i18n</code> tag.</p><h3 id="Localization-UsinggetTextfromaTag">Using <code>getText</code> from a Tag</h3><p>To display i18n text, use a call to <code>getText</code> in the <a shape="rect" href="property.html">property</a> tag, or any other tag, such as the UI tags. (The <code>getText</code> technique is especially useful for labels of UI tags.)</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<script class="brush: xml; gutter: false; theme: Default" type="syntaxhighlighter"><![CDATA[

&lt;s:property value=&quot;getText(&#39;some.key&#39;)&quot; /&gt;

]]></script>
</div></div><div class="confluence-information-macro confluence-information-macro-note"><span class="aui-icon aui-icon-small aui-iconfont-warning confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>The default implementation of <code>TextProvider</code> which is used in <code>ActionSupport</code> perform evaluation of value read from bundle base on the provided key, see <a shape="rect" href="localizing-output.html">Localizing Output</a> for an example.</p></div></div><h3 id="Localization-Usingthetexttag">Using the <code>text</code> tag</h3><p>The <a shape="rect" href="text.html">text</a> tag retrieves a message from the default resource bundle.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<script class="brush: xml; gutter: false; theme: Default" type="syntaxhighlighter"><![CDATA[

&lt;-- Fourth Example --&gt;
&lt;s:text name=&quot;some.key&quot; /&gt;

&lt;-- Fifth Example --&gt;
&lt;s:text name=&quot;some.invalid.key&quot; &gt;
   The Default Message That Will Be Displayed
&lt;/s:text&gt;

]]></script>
</div></div><h3 id="Localization-UsingtheI18ntag">Using the <code>I18n</code> tag</h3><p>The <a shape="rect" href="i18n.html">i18n</a> tag pushes an arbitrary resource bundle on to the value stack. Other tags within the scope of the i18n tag can display messages from that resource bundle.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<script class="brush: xml; gutter: false; theme: Default" type="syntaxhighlighter"><![CDATA[

&lt;s:i18n name=&quot;some.package.bundle&quot; &gt;
     &lt;s:text name=&quot;some.key&quot; /&gt;
&lt;/s:i18n&gt;

]]></script>
</div></div><div class="confluence-information-macro confluence-information-macro-tip"><span class="aui-icon aui-icon-small aui-iconfont-approve confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>Internationalizing SiteMesh decorators is possible, but there are quirks. See <a shape="rect" href="https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=33343">SiteMesh Plugin</a> for more.</p></div></div><h3 id="Localization-UsingtheKeyattributeofUITags">Using the Key attribute of UI Tags</h3><p>The key attribute of most UI tags can be used to retrieve a message from a resource bundle:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">&lt;s:textfield key="some.key" name="textfieldName"/&gt;</pre>
</div></div><h2 id="Localization-I18nInterceptor">I18n Interceptor</h2><p>Essentially, the i18n Interceptor pushes a locale into the ActionContext map upon every request. The framework components that support localization all utilize the ActionContext locale. See <a shape="rect" href="i18n-interceptor.html">I18n Interceptor</a> for details.</p><h2 id="Localization-GlobalResources(struts.custom.i18n.resources)instruts.properties">Global Resources (struts.custom.i18n.resources) in <code>struts.properties</code></h2><p></p><p></p><p>
A global resource bundle could be specified programmatically, as well as the locale.
</p><h2 id="Localization-FormattingDatesandNumbers">Formatting Dates and Numbers</h2><p>See <a shape="rect" href="formatting-dates-and-numbers.html">Formatting Dates and Numbers</a> for more details and examples.</p><h2 id="Localization-ComparisonwithStruts1">Comparison with Struts 1</h2><p>Struts 1 users should be familiar with the application.properties resource bundle, where you can put all the messages in the application that are going to be translated. Struts 2, though, splits the resource bundles per action or model class, and you may end up with duplicated messages in those resource bundles. A quick fix for that is to create a file called ActionSupport.properties in com/opensymphony/xwork2 and put it on your classpath. This will only work well if all your actions subclass XWork2's ActionSupport.</p><h2 id="Localization-Next:">Next: <a shape="rect" href="type-conversion.html">Type Conversion</a></h2></div>
        </div>

        
    </div>
</div>
<div class="footer">
    Generated by CXF SiteExporter
</div>
</body>
</html>
